package com.teensoft.base.dao.imp;

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.teensoft.base.dao.IDAO;
import com.teensoft.base.exception.DAOException;

@SuppressWarnings("unchecked")
public class HibernateDAO implements IDAO<Object> {

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public Object get(Class refClass, Serializable key) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return get(refClass, key, session);
	}

	private Object get(Class refClass, Serializable key, Session s) {
		return s.get(refClass, key);
	}

	public Object load(Class refClass, Serializable key) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return load(refClass, key, session);
	}

	private Object load(Class refClass, Serializable key, Session s) {
		return s.load(refClass, key);
	}

	public List findAll(Class refClass, Order defaultOrder) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return findAll(refClass, session, defaultOrder);
	}

	private List findAll(Class refClass, Session s, Order defaultOrder) {
		Criteria crit = s.createCriteria(refClass);
		if (defaultOrder != null)
			crit.addOrder(defaultOrder);
		return crit.list();
	}

	public Query getQuery(String queryStr) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return getQuery(queryStr, session);
	}

	private Query getQuery(String queryStr, Session s) {
		return s.createQuery(queryStr);
	}

	public Query getQuery(String queryStr, Serializable param)
			throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return getQuery(queryStr, param, session);
	}

	private Query getQuery(String queryStr, Serializable param, Session s) {
		Query q = getQuery(queryStr, s);
		q.setParameter(0, param);
		return q;
	}

	public Query getQuery(String queryStr, Serializable params[])
			throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return getQuery(queryStr, params, session);
	}

	private Query getQuery(String queryStr, Serializable params[], Session s) {
		Query q = getQuery(queryStr, s);
		if (params != null) {
			for (int i = 0; i < params.length; i++)
				q.setParameter(i, params[i]);

		}
		return q;
	}

	public Query getQuery(String queryStr, Map params) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return getQuery(queryStr, params, session);
	}

	private Query getQuery(String queryStr, Map params, Session s) {
		Query q = getQuery(queryStr, s);
		if (params != null) {
			java.util.Map.Entry entry;
			for (Iterator i = params.entrySet().iterator(); i.hasNext(); q
					.setParameter((String) entry.getKey(), entry.getValue()))
				entry = (java.util.Map.Entry) i.next();

		}
		return q;
	}

	public List getList(String queryStr) throws DAOException {
		return getQuery(queryStr).list();
	}

	public List getList(String queryStr, Serializable param)
			throws DAOException {
		return getQuery(queryStr, param).list();
	}

	public List getList(String queryStr, Serializable params[])
			throws DAOException {
		return getQuery(queryStr, params).list();
	}

	public List getList(String queryStr, Map params) throws DAOException {
		return getQuery(queryStr, params).list();
	}

	public Serializable save(Object obj) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return save(obj, session);
	}

	private Serializable save(Object obj, Session s) {
		return s.save(obj);
	}

	public void saveOrUpdate(Object obj) throws DAOException {
		try {
			Session session = SessionFactoryUtils.getSession(
					getSessionFactory(), false);
			saveOrUpdate(obj, session);
		} catch (HibernateException heex) {
			throw SessionFactoryUtils.convertHibernateAccessException(heex);
		}
	}

	private void saveOrUpdate(Object obj, Session s) {
		s.saveOrUpdate(obj);
	}

	public void update(Object obj) throws DAOException {
		try {
			Session session = SessionFactoryUtils.getSession(
					getSessionFactory(), false);
			update(obj, session);
		} catch (HibernateException heex) {
			throw SessionFactoryUtils.convertHibernateAccessException(heex);
		}
	}

	private void update(Object obj, Session s) {
		s.update(obj);
	}

	public int delete(Query query) throws DAOException {
		Session session = SessionFactoryUtils.getSession(getSessionFactory(),
				false);
		return delete(query, session);
	}

	private int delete(Query query, Session s) {
		List list = query.list();
		for (Iterator i = list.iterator(); i.hasNext(); delete(i.next(), s))
			;
		return list.size();
	}

	public void delete(Class refClass, Serializable key) throws DAOException {
		try {
			Session session = SessionFactoryUtils.getSession(
					getSessionFactory(), false);
			delete(get(refClass, key, session), session);
		} catch (HibernateException heex) {
			throw SessionFactoryUtils.convertHibernateAccessException(heex);
		}
	}

	public void delete(Class refClass, Serializable key[]) throws DAOException {
		try {
			Session session = SessionFactoryUtils.getSession(
					getSessionFactory(), false);
			for (int i = 0; i < key.length; i++)
				delete(get(refClass, key[i], session), session);

		} catch (HibernateException heex) {
			throw SessionFactoryUtils.convertHibernateAccessException(heex);
		}
	}

	private void delete(Object obj, Session s) {
		s.delete(obj);
	}

	protected void refresh(Object obj, Session s) {
		s.refresh(obj);
	}

	public int updateObject(String queryStr, Serializable params[])
			throws DAOException {
		return getQuery(queryStr, params).executeUpdate();
	}

	private SessionFactory sessionFactory;

}
